package com.berry.MedCheck.widget;

import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.berry.MedCheck.GraphActivity;
import com.berry.MedCheck.R;
import com.berry.MedCheck.Utils;
import com.berry.MedCheck.db.UserDB;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: Airay.Rong
 * Date: 13-12-5
 * Time: 下午5:04
 * To change this template use File | Settings | File Templates.
 */
public class LineChart  extends View {
	private Paint mBitmapPaint;
	private Paint       mPaint;
	private Paint       mPaintGrid;
	private Paint       mPaintLine1;
	private Paint       mPaintLine2;
	private Paint       mPaintTest;
	private Bitmap mBitmap;

	private List<Long > mTimesList;
	private List<Integer> mData1List;
	private List<Integer> mData2List;
	private List<Map<String,Integer>> mData1Pos;
	private List<Map<String,Integer>> mData2Pos;
	private List<Map<String,Integer>> mTimePos;
	private int myDX;
	private int myDY;
	private int mRowHeight;
	private int mColWidth;
	private int mUsefulChartX;
	private int mUsefulChartDX;
	private int mUsefulChartY;
	private int mUsefulChartDY;
	private final static int mMarginLeftRight = 10;
	private final static int LEVEL_TEXT_DX = 0;
	private final static int MAX_VALUE = 250;
	private final static int CHART_ROW = MAX_VALUE / 25;
	private final static int CHART_COL = Utils.GRAPHY_POINT_NUM;
	private final static int CHART_HEAD_HEIGHT = 0 ;
	private final static int CHART_END_HEIGHT = 20 ;
	private final static int LINE_COLOR_1 = 0xFF5F8BC5;
	private final static int LINE_COLOR_2 = 0xFFFF8040;
	private final static int TOUCH_MOVE_OFFSET = 100;
	private float xSave;
	private float ySave;
	private float xSave2;
	private float ySave2;
	private float mTitleTextSize;
	private float mLevelTextSize;
	private float mValueTextSize;
	private float mLineWidth;
	private int nTouchedIndex = 0;
	private TextView mTVDate;
	private TextView mTVSpo2;
	private TextView mTVPR;
	private  float LINE_WIDTH ;



	private loadDataCallback mCallback ;


	public interface loadDataCallback{
		void loadData(boolean old);
	}
	public LineChart(Context c) {
		super(c);
	}
	public LineChart(Context context, AttributeSet attrs) {
		super(context, attrs);
		mBitmapPaint = new Paint(Paint.DITHER_FLAG);

		setupPaints();
		mTimesList = new ArrayList<Long>();
		mData1List = new ArrayList<Integer>();
		mData2List = new ArrayList<Integer>();

		mData1Pos = new ArrayList<Map<String,Integer>>();
		mData2Pos = new ArrayList<Map<String,Integer>>();
		mTimePos = new ArrayList<Map<String,Integer>>();

//		mPaintTest = new Paint();
//		mPaintTest.setColor(Color.WHITE);
//		mPaintTest.setAntiAlias(true);
//		mPaintTest.setStrokeWidth(6);
//		mPaintTest.setStyle(Paint.Style.FILL);
//		mPath.moveTo(0, 0);
//		mPath.lineTo(300, 0);
//		//mPath.lineTo(300, 50);
//		//mPath.lineTo(350,50);
//		mPath.arcTo(new RectF(250, 0, 350, 100),-90, 90);
//		mPath.lineTo(300,50);
//		mPath.lineTo(350,50);
//		mPath.lineTo(350,200);
//		mPath.arcTo(new RectF(250, 150, 350, 250), 0, 90);
//		mPath.lineTo(50,250);
//		mPath.arcTo(new RectF(0, 150, 100, 250), 90, 90);
//
//		mPath.close();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				xSave = event.getX();
				ySave = event.getY();
				xSave2 = xSave;
				ySave2 = ySave;
				break;
			case MotionEvent.ACTION_MOVE:
				if (mCallback == null) {
					return true;
				}
				float x = event.getX();
				float y = event.getY();
				if (Math.abs(x - xSave) > TOUCH_MOVE_OFFSET) {
					if (x > xSave) {
						mCallback.loadData(true);
					} else {
						mCallback.loadData(false);
					}
					xSave = x;
					ySave = x;
				}
				break;
			case MotionEvent.ACTION_UP:
				x = event.getX();
				y = event.getY();
				if (Math.abs(x - xSave2) < TOUCH_MOVE_OFFSET) {
					checkToShowValues(xSave, ySave);
					invalidate();
				}

				break;
		}
		return true;
	}

	private void checkToShowValues(float xSave, float ySave) {
		int index = (int) ((xSave - mUsefulChartX) / mColWidth);
		if (mTimesList.size() == 0 || index < 0 || index > (CHART_COL-1)) {
			return;
		}
		nTouchedIndex = index;
	}

	private void updateValues() {
		if (mTimesList.size() == 0 ) {
			return;
		}
		if (mTVDate != null) {
			mTVDate.setText(Utils.getFullDate(mTimesList.get(nTouchedIndex)));
		}
		if (mData1List.size() == 0 || mData2List.size() == 0) {
			return;
		}
		int nSp02 = mData1List.get(nTouchedIndex);
		int nPr = mData2List.get(nTouchedIndex);
		if (mTVSpo2 != null) {
			mTVSpo2.setText(Integer.toString(nSp02));
		}
		if (mTVPR != null) {
			mTVPR.setText(Integer.toString(nPr));
		}
	}

	public void setTimeList(ArrayList<Long> timeList) {
		mTimesList.clear();
		for (int i = 0; i < CHART_COL; i++) {
			mTimesList.add(timeList.get(i));
		}
		invalidate();
	}
	public void setData1List(ArrayList<Integer> list) {
		//list保存最后6个数据，按照时间升序排列，即第六个数据，是最新的数据
		if (mData1List.size() != 0) {
			mData1List.clear();
			for (int i = 0; i < CHART_COL; i++) {
				mData1List.add(list.get(i));
			}
			calcLine1Pos();
			invalidate();
		} else {
			mData1List.clear();
			for (int i = 0; i < CHART_COL; i++) {
				mData1List.add(list.get(i));
			}
		}

	}
	public void setData2List(ArrayList<Integer> list) {
		//list保存最后6个数据，按照时间升序排列，即第六个数据，是最新的数据
		if (mData2List.size() != 0) {
			mData2List.clear();
			for (int i = 0; i < CHART_COL; i++) {
				mData2List.add(list.get(i));
			}
			calcLine2Pos();
			invalidate();
		} else {
			mData2List.clear();
			for (int i = 0; i < CHART_COL; i++) {
				mData2List.add(list.get(i));
			}
		}

	}

	public void setFullData(ArrayList<Map<String, Long>> list) {
		mData1List.clear();
		mData2List.clear();
		mTimesList.clear();
		Map<String,Long> map = null;
		Log.d("meauserData", "get Spo2= **************");
		for (int i = CHART_COL-1; i >= 0 ; i--) {
			map = list.get(i);
			Long dataSpo2 = map.get(UserDB.DBColumns.SPO2);
			Long dataPR = map.get(UserDB.DBColumns.PR);
			Long dataDate = map.get(UserDB.DBColumns.DATE);
			Log.d("meauserData", "get Spo2=" + dataSpo2);
			mData1List.add(dataSpo2.intValue());
			mData2List.add(dataPR.intValue());
			mTimesList.add(dataDate);
		}
		Log.d("meauserData", "get Spo2= **************");
		calcLine1Pos();
		calcLine2Pos();
		invalidate();
	}

	public   void setDateTextView(TextView textView) {
		  mTVDate = textView;
	}

	public void setValueTextView(TextView spo2, TextView pr) {
		mTVSpo2 = spo2;
		mTVPR = pr;
	}

//	private void copyArrayListData(ArrayList<T> from, ArrayList<T> to) {
//		for (int i = 0; i < CHART_COL; i++) {
//			to.add(from.get(i));
//		}
//	}

	public void setLoadDataCallback(loadDataCallback cb) {
		mCallback = cb;
	}

	public void setTextSize(float title, float level, float value) {
		mTitleTextSize = title;
		mLevelTextSize = level;
		mValueTextSize = value;
	}

	public void setLineWidth(float width) {
		mLineWidth = width;
	}
	private void calcTimePos() {
		//计算6个坐标点的X坐标
		mTimePos.clear();
		for (int i = 0; i < CHART_COL; i++) {
			Map<String, Integer> map = new HashMap<String, Integer>();
			map.put("x", mUsefulChartX +  + mColWidth * i);
			map.put("y", (mRowHeight*6));
			mTimePos.add(map);
		}
	}
	private void calcLine1Pos() {
		int Xoffset = mColWidth / 2;
		int YOffset = mRowHeight / 2;
		mData1Pos.clear();
		if (mData1List.size() != CHART_COL) {
			return;
		}
		for (int i = 0; i < CHART_COL; i++) {
			int value = mData1List.get(i);
			Map<String, Integer> map = new HashMap<String, Integer>();
			map.put("x", mUsefulChartX + Xoffset + mColWidth * i);
			int yPos = myDY -CHART_END_HEIGHT - value * mUsefulChartDY / MAX_VALUE + mRowHeight/2;
			map.put("y", yPos);
			if (value == 0) {
				map.put("show", 0);
			} else {
				map.put("show", 1);
			}

			mData1Pos.add(map);
		}
	}

	private void calcLine2Pos() {
		int offset = mColWidth / 2;
		//计算6个坐标点的X坐标
		int Xoffset = mColWidth / 2;
		int YOffset = mRowHeight / 2;
		mData2Pos.clear();
		if (mData2List.size() != CHART_COL) {
			return;
		}
		for (int i = 0; i < CHART_COL; i++) {
			int value = mData2List.get(i);
			Map<String, Integer> map = new HashMap<String, Integer>();
			map.put("x", mUsefulChartX + Xoffset + mColWidth * i);
			int yPos = myDY-CHART_END_HEIGHT  - value * mUsefulChartDY / MAX_VALUE + mRowHeight/2;
			map.put("y", yPos);
			if (value == 0) {
				map.put("show", 0);
			} else {
				map.put("show", 1);
			}
			mData2Pos.add(map);
		}
	}
	private void setupPaints(){
		LINE_WIDTH =   getResources().getDimension(R.dimen.graph_line_width);
		mPaint = new Paint();
		mPaint.setColor(Color.WHITE);
		mPaint.setAntiAlias(true);
		mPaint.setStrokeWidth(6);
		mPaint.setTextAlign(Paint.Align.LEFT);

		mPaintGrid = new Paint();
		mPaintGrid.setColor(Color.WHITE);
		mPaintGrid.setAntiAlias(false);
		mPaintGrid.setStrokeWidth(4);

		mPaintLine1 = new Paint();
		mPaintLine1.setAntiAlias(true);
		mPaintLine1.setDither(true);
		mPaintLine1.setColor(LINE_COLOR_1);
		mPaintLine1.setStyle(Paint.Style.STROKE);
		mPaintLine1.setStrokeJoin(Paint.Join.ROUND);
		mPaintLine1.setStrokeCap(Paint.Cap.ROUND);
		mPaintLine1.setStrokeWidth(LINE_WIDTH);

		mPaintLine2 = new Paint();
		mPaintLine2.setAntiAlias(true);
		mPaintLine2.setDither(true);
		mPaintLine2.setColor(LINE_COLOR_2);
		mPaintLine2.setStyle(Paint.Style.STROKE);
		mPaintLine2.setStrokeJoin(Paint.Join.ROUND);
		mPaintLine2.setStrokeCap(Paint.Cap.ROUND);
		mPaintLine2.setStrokeWidth(LINE_WIDTH);

	}



	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		calcPositions(w, h);
		mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
		calcLine1Pos() ;
		calcLine2Pos() ;
		//calcTimePos();
	}


	private void calcPositions(int w, int h) {
		myDX = w;
		myDY = h;

		mRowHeight = (myDY-CHART_HEAD_HEIGHT-CHART_END_HEIGHT) / CHART_ROW;
		mUsefulChartX = 0 + mMarginLeftRight + LEVEL_TEXT_DX;
		mUsefulChartDX = myDX - mUsefulChartX ;
		mUsefulChartY = CHART_HEAD_HEIGHT;
		mUsefulChartDY = (myDY - CHART_HEAD_HEIGHT-CHART_END_HEIGHT);
		mColWidth = mUsefulChartDX / CHART_COL;
	}

	private void drawLevelText(Canvas canvas) {
		int offset = mRowHeight;
		mPaint.setTextAlign(Paint.Align.LEFT);
		mPaint.setTextSize(mLevelTextSize);
		canvas.drawText("250", mMarginLeftRight, CHART_HEAD_HEIGHT + offset + mRowHeight * (CHART_ROW - 10)-mRowHeight/2, mPaint);
		canvas.drawText("200", mMarginLeftRight, CHART_HEAD_HEIGHT + offset + mRowHeight * (CHART_ROW - 8)-mRowHeight/2, mPaint);
		canvas.drawText("150", mMarginLeftRight, CHART_HEAD_HEIGHT + offset + mRowHeight * (CHART_ROW - 6)-mRowHeight/2, mPaint);
		canvas.drawText("100", mMarginLeftRight, CHART_HEAD_HEIGHT + offset + mRowHeight * (CHART_ROW - 4)-mRowHeight/2, mPaint);
		canvas.drawText("50", mMarginLeftRight, CHART_HEAD_HEIGHT + offset + mRowHeight * (CHART_ROW - 2)-mRowHeight/2, mPaint);
		canvas.drawText("0", mMarginLeftRight, CHART_HEAD_HEIGHT + offset + mRowHeight * (CHART_ROW - 0)-mRowHeight/2, mPaint);

	}
	private void drawGrid(Canvas canvas) {
		//横线
		for (int i = 0; i <= CHART_ROW; i++) {
			canvas.drawLine(0,(mRowHeight*i)+CHART_HEAD_HEIGHT,myDX,(mRowHeight*i)+CHART_HEAD_HEIGHT,mPaintGrid);
		}
		//竖线
		for (int i = 0; i <= (CHART_COL); i++) {
			canvas.drawLine(mUsefulChartX+mColWidth*i, mRowHeight,mUsefulChartX+mColWidth*i,mRowHeight *CHART_COL,mPaintGrid);
		}


	}
	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
		//canvas.drawPath(mPath, mPaintTest);
		//drawGrid(canvas);
		//drawTitle(canvas);
		//drawLevelText(canvas);
		//drawTime(canvas);
		drawLine1(canvas);
		drawLine2(canvas);
		//drawValue(canvas);
		updateValues();



	}

	private void drawTitle(Canvas canvas) {
		int offset = mRowHeight / 2 + 20;
		mPaint.setTextAlign(Paint.Align.RIGHT);
		mPaint.setTextSize(mTitleTextSize);
		int x1 = mUsefulChartX + mUsefulChartDX / 6 * 2;
		int x2 = mUsefulChartX + mUsefulChartDX / 6 * 4;
		canvas.drawText("SpO₂", x1, offset, mPaint);
		canvas.drawText("Rate", x2, offset, mPaint);

		canvas.drawLine(x1 + 20, mRowHeight , x1 + mUsefulChartDX / 6, mRowHeight , mPaintLine1);
		canvas.drawLine(x2 + 20, mRowHeight , x2 + mUsefulChartDX / 6, mRowHeight , mPaintLine2);

	}
	private void drawValue(Canvas canvas) {
		if (mData1List.size() == 0 || mData2List.size() == 0) {
			return;
		}
		int nSp02 = mData1List.get(nTouchedIndex);
		int nPr = mData2List.get(nTouchedIndex);
		int offset = mRowHeight / 2 +5;
		mPaint.setTextAlign(Paint.Align.LEFT);
		mPaint.setTextSize(mValueTextSize);
		int x1 = mUsefulChartX + mUsefulChartDX / 6 * 2 + mUsefulChartDX / 6 / 2;
		int x2 = mUsefulChartX + mUsefulChartDX / 6 * 4 + mUsefulChartDX / 6 / 2;
		canvas.drawText(Integer.toString(nSp02), x1, offset, mPaint);
		canvas.drawText(Integer.toString(nPr), x2, offset, mPaint);


	}
	private void drawTime(Canvas canvas) {
		if (mTimesList.size() != 0) {
			int offsetY = mRowHeight/2+20;
			int offsetX = mColWidth/2;
			mPaint.setTextSize(mLevelTextSize);
			mPaint.setTextAlign(Paint.Align.CENTER);
			for (int i = 0; i < CHART_COL; i++) {
				String value = Utils.getTime(mTimesList.get(i));
				Map<String, Integer> map = mTimePos.get(i);
				canvas.drawText(value, map.get("x")+offsetX, map.get("y")+offsetY, mPaint);
			}
			mPaint.setTextAlign(Paint.Align.LEFT);
		}
	}

	private void drawLine1(Canvas canvas) {
		if (mData1List.size() != 0) {
			Path mLin1 = new Path();
			boolean bFirst = true;
			for (int i = 0; i < CHART_COL; i++) {
				Map<String, Integer> map = mData1Pos.get(i);
				if (map.get("show") == 0){
					continue;
				}
				if (bFirst == true) {
					mLin1.moveTo(map.get("x"), map.get("y"));
					bFirst = false;
				} else {
					mLin1.lineTo(map.get("x"), map.get("y"));
				}
			}
			canvas.drawPath(mLin1,mPaintLine1);
			for (int i = 0; i < CHART_COL; i++) {
				Map<String, Integer> map = mData1Pos.get(i);
				if (map.get("show") == 0){
					continue;
				}
				canvas.drawCircle(map.get("x"), map.get("y"), LINE_WIDTH - 2, mPaintLine1);
				if (i == nTouchedIndex) {
					canvas.drawCircle(map.get("x"), map.get("y"), LINE_WIDTH + 2, mPaintLine1);
				}
			}
		}
	}
	private void drawLine2(Canvas canvas) {
		if (mData2List.size() != 0) {
			Path mLine = new Path();
			boolean bFirst = true;
			for (int i = 0; i < CHART_COL; i++) {
				Map<String, Integer> map = mData2Pos.get(i);
				if (map.get("show") == 0) {
					continue;
				}
				if (bFirst == true) {
					mLine.moveTo(map.get("x"), map.get("y"));
					bFirst = false;
				} else {
					mLine.lineTo(map.get("x"), map.get("y"));
				}
			}
			canvas.drawPath(mLine,mPaintLine2);
			for (int i = 0; i < CHART_COL; i++) {
				Map<String, Integer> map = mData2Pos.get(i);
				if (map.get("show") == 0){
					continue;
				}
				canvas.drawCircle(map.get("x"), map.get("y"), LINE_WIDTH-2, mPaintLine2);
				if (i == nTouchedIndex) {
					canvas.drawCircle(map.get("x"), map.get("y"), LINE_WIDTH+2, mPaintLine2);
				}
			}
		}
	}
}
